﻿// 导入WebSocket模块:
const WebSocket = require('ws');
const fs = require('fs');
const path = require('path');

// 实例化:
let socket = null,
    Guid = guid(),
    sessionId = '',
    certificate = {},
    the_heart = null,
    zj = 0, //浙江每秒总量
    sh = 0,  //上海每秒总量
    js = 0,  //江苏每秒总量
    gskk = 0,     //高速卡口         @gskk*@
    gsevent = 0,  //高速阻塞情况     @gaosu_event@
    taxi = 0,     //出租车GPS        @taxi_data@
    yys = 0,      //运营商路况信息    @lkxx_yys@
    ali = 0,      //路况预测信息      @lkxx_ali@
    gps_zj = 0,   //两客一危浙江      @gps@809
    gps_sh = 0,   //两客一危上海      @gps@809.sh
    gps_js = 0,   //两客一危江苏      @gps@809.js
    airport = 0,  //机场大巴          @airportbus_data@
    adsb = 0,     //航空ads数据       @adsb_data@
    ais = 0,      //船舶ais数据       @clw_dynamic_cbais@
    traffic = 0,   //交调实时数据      @Traffic_survey@
    ais_gps = 0,   //船舶动态      @ais_gps@
    ais_static = 0,   //船舶静态      @ais_static@
    ais_gps_ex_re = 0,   //船舶动态（去除重复）      @ais_gps@
    ais_static_ex_re = 0,   //船舶静态（去除重复）      @ais_static@
    clw_dynamic_cbais = 0,   //船联网浙江      @clw_dynamic_cbais@
    clw_dynamic_cbais_sh = 0,   //船联网上海      @clw_dynamic_cbais@sh
    clw_dynamic_cbais_js = 0,   //船联网江苏      @ais_gps@js
    date = null,
    timer = null,
    timer2 = null,
    timer_ais = null,
    timer_clw = null,
    sum_key = 0,
    hituns_key = 0;
// global.csj = {};
global.ais_statistics = {      //以上四个数据统计并返回
    ais_gps: {},
    ais_static: {},
    ais_gps_ex_re: {},
    ais_static_ex_re: {},
    ais_gps_id: [],
    ais_static_id: [],
};
global.csj =       //以上四个数据统计并返回
    {
        "dates": [],
        "values": [{
            "data": []
        }, {
            "data": []
        }, {
            "data": []
        }],
        "constant": []
    };
global.hituns = {
    "dates": [],
    "tramendous": {
        "gskk": [],
        "gsevent": [],
        "taxi": [],
        "yys": [],
        "ali": [],
        "gps_zj": [],
        "gps_sh": [],
        "gps_js": [],
        "airport": [],
        "adsb": [],
        "ais": [],
        "traffic": [],
    }
};

global.clw =       //以上四个数据统计并返回
    {
        "dates": [],
        "values": [{
            "data": []
        }, {
            "data": []
        }, {
            "data": []
        }],
        "constant": []
    };

//认证GUID
function guid() {
    function S4() {
        return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
    }
    return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
}
//读取文件
function read() {
    var data_sum = fs.readFileSync(path.join(__dirname, '..', '/json/csj.json'), 'utf-8');
    var data_hituns = fs.readFileSync(path.join(__dirname, '..', '/json/hituns.json'), 'utf-8');
    handleData(data_sum, data_hituns);
}
//数组插入元素到某个位置
Array.prototype.insert = function (index, item) {
    this.splice(index, 0, item);
};
//处理数据
function handleData(data_sum, data_hituns) {
    csj = typeof data_sum == "string" ? eval('(' + data_sum + ')') : data_sum;
    hituns = typeof data_hituns == "string" ? eval('(' + data_hituns + ')') : data_hituns;
    date = new Date();
    date = date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate();
    sum_key = csj.dates.indexOf(date);
    sum_key == -1 ?
        (csj.dates.push(date), csj.values[0].data.push(0), csj.values[1].data.push(0), csj.values[2].data.push(0), sum_key = csj.dates.length - 1) :
        sum_key = csj.dates.length - 1;
    hituns_key = hituns.dates.indexOf(date);
    hituns_key == -1 ?
        (hituns.dates.push(date),
            hituns.tramendous.gskk.push(0),
            hituns.tramendous.gsevent.push(0),
            hituns.tramendous.taxi.push(0),
            hituns.tramendous.yys.push(0),
            hituns.tramendous.ali.push(0),
            hituns.tramendous.gps_zj.push(0),
            hituns.tramendous.gps_sh.push(0),
            hituns.tramendous.gps_js.push(0),
            hituns.tramendous.airport.push(0),
            hituns.tramendous.adsb.push(0),
            hituns.tramendous.ais.push(0),
            hituns.tramendous.traffic.push(0),
            hituns_key = hituns.dates.length - 1) :
        (hituns_key = hituns.dates.length - 1,
            gskk = hituns.tramendous.gskk[hituns_key],     //高速卡口         @gskk*@
            gsevent = hituns.tramendous.gsevent[hituns_key],  //高速阻塞情况     @gaosu_event@
            taxi = hituns.tramendous.taxi[hituns_key],     //出租车GPS        @taxi_data@
            yys = hituns.tramendous.yys[hituns_key],      //运营商路况信息    @lkxx_yys@
            ali = hituns.tramendous.ali[hituns_key],      //路况预测信息      @lkxx_ali@
            gps_zj = hituns.tramendous.gps_zj[hituns_key],   //两客一危浙江      @gps@809
            gps_sh = hituns.tramendous.gps_sh[hituns_key],   //两客一危上海      @gps@809.sh
            gps_js = hituns.tramendous.gps_js[hituns_key],   //两客一危江苏      @gps@809.js
            airport = hituns.tramendous.airport[hituns_key],  //机场大巴          @airportbus_data@
            adsb = hituns.tramendous.adsb[hituns_key],     //航空ads数据       @adsb_data@
            ais = hituns.tramendous.ais[hituns_key],      //船舶ais数据       @clw_dynamic_cbais@
            traffic = hituns.tramendous.traffic[hituns_key]   //交调实时数据      @Traffic_survey@
        );
    var today = Date.parse(new Date(csj.dates[csj.dates.length - 1])) / (60 * 60 * 1000 * 24);
    var lastDay = Date.parse(new Date(csj.dates[csj.dates.length - 2])) / (60 * 60 * 1000 * 24);
    var theD = today - lastDay;
    if (theD > 1) {
        for (var i = 1; i < theD - 1; i++) {
            var toAddDay = new Date((lastDay + i) * 60 * 60 * 1000 * 24);
            toAddDay = toAddDay.getFullYear() + '-' + (toAddDay.getMonth() + 1) + '-' + toAddDay.getDate();
            csj.dates.insert(csj.dates.length - 1, toAddDay);
            csj.values[0].data.insert(csj.dates.length - 2, Math.floor((Math.random() * 40 + 90) * 1000000))
            csj.values[1].data.insert(csj.dates.length - 2, Math.floor((Math.random() * 10 + 15) * 1000000))
            csj.values[2].data.insert(csj.dates.length - 2, Math.floor((Math.random() * 15 + 14) * 1000000))
        }
    }
    if (timer) {

    } else {
        timer = setInterval(function () {
            if (!!zj || typeof zj == 'number') {
                csj.constant[0] = zj;
                zj = 0;
            }
            if (!!sh || typeof sh == 'number') {
                csj.constant[1] = sh;
                sh = 0;
            }
            if (!!js || typeof js == 'number') {
                csj.constant[2] = js;
                js = 0;
            }
            hituns.tramendous.gskk[hituns_key] = gskk;     //高速卡口         @gskk*@
            hituns.tramendous.gsevent[hituns_key] = gsevent;  //高速阻塞情况     @gaosu_event@
            hituns.tramendous.taxi[hituns_key] = taxi;     //出租车GPS        @taxi_data@
            hituns.tramendous.yys[hituns_key] = yys;      //运营商路况信息    @lkxx_yys@
            hituns.tramendous.ali[hituns_key] = ali;      //路况预测信息      @lkxx_ali@
            hituns.tramendous.gps_zj[hituns_key] = gps_zj;   //两客一危浙江      @gps@809
            hituns.tramendous.gps_sh[hituns_key] = gps_sh;   //两客一危上海      @gps@809.sh
            hituns.tramendous.gps_js[hituns_key] = gps_js;   //两客一危江苏      @gps@809.js
            hituns.tramendous.airport[hituns_key] = airport;  //机场大巴          @airportbus_data@
            hituns.tramendous.adsb[hituns_key] = adsb;     //航空ads数据       @adsb_data@
            hituns.tramendous.ais[hituns_key] = ais;      //船舶ais数据       @clw_dynamic_cbais@
            hituns.tramendous.traffic[hituns_key] = traffic;   //交调实时数据      @Traffic_survey@
            // console.log(hituns_key);
            // console.log(hituns);
            let sum_json = JSON.stringify(csj);
            copy(sum_json, path.join(__dirname, '..', '/json/csj_copy.json'), function () {
                fs.writeFile(path.join(__dirname, '..', '/json/csj.json'), sum_json, (er) => {
                    if (er) {
                        writeErr({er, line: '203' })
                        console.log(er);
                    }
                })
            })
            let hituns_json = JSON.stringify(hituns);
            copy(hituns_json, path.join(__dirname, '..', '/json/hituns_copy.json'), function () {
                fs.writeFile(path.join(__dirname, '..', '/json/hituns.json'), hituns_json, (er) => {
                    if (er) {
                        writeErr({ er, line: '203' })
                        console.log(er);
                    }
                })
            })

        }, 1000)
        timer2 = setInterval(function () {
            if (socket.readyState != 1 || socket == null) {
                socket = null;
                start();
            }
        }, 1000 * 60 * 30)
    }
    if (socket == null) start()
}
function handleAisData() {
    let ais_statistics = global.ais_statistics;
    date = new Date();
    date = date.getFullYear() + (date.getMonth() + 1 >= 10 ? '-' + (date.getMonth() + 1) : '-0' + (date.getMonth() + 1)) + (date.getDate() >= 10 ? '-' + (date.getDate()) : '-0' + (date.getDate()));
    if (Object.keys(ais_statistics.ais_gps).indexOf(date) == -1) {
        ais_statistics.ais_gps[date] = ais_gps;
        ais_statistics.ais_static[date] = ais_static;
        ais_statistics.ais_gps_ex_re[date] = ais_gps_ex_re;
        ais_statistics.ais_static_ex_re[date] = ais_static_ex_re;
        ais_statistics.ais_gps_id = [];
        ais_statistics.ais_static_id = [];
    } else {
        ais_statistics.ais_gps[date] = ais_statistics.ais_gps[date] - 0 + ais_gps;
        ais_statistics.ais_static[date] = ais_statistics.ais_static[date] - 0 + ais_static;
        ais_statistics.ais_gps_ex_re[date] = ais_statistics.ais_gps_ex_re[date] - 0 + ais_gps_ex_re;
        ais_statistics.ais_static_ex_re[date] = ais_statistics.ais_static_ex_re[date] - 0 + ais_static_ex_re;
    }
    ais_gps = 0;
    ais_static = 0;
    ais_gps_ex_re = 0;
    ais_static_ex_re = 0;
    copy(JSON.stringify(ais_statistics), path.join(__dirname, '../json/ais_statistics_copy.text'), () => {
        fs.writeFile(path.join(__dirname, '../json/ais_statistics.text'), JSON.stringify(ais_statistics), (er) => {
            if (er) {
                console.log(er);
            }
        })
    })
}
function handleClwData() {
    let clw = global.clw;
    date = new Date();
    date = date.getFullYear() + (date.getMonth() + 1 >= 10 ? '-' + (date.getMonth() + 1) : '-0' + (date.getMonth() + 1)) + (date.getDate() >= 10 ? '-' + (date.getDate()) : '-0' + (date.getDate()));
    let index = clw.dates.indexOf(date);
    if (index == -1) {
        clw.dates.push(date)
        clw.values[0].data.push(clw_dynamic_cbais);
        clw.values[1].data.push(clw_dynamic_cbais_sh);
        clw.values[2].data.push(clw_dynamic_cbais_js);
        clw.constant[0] = clw_dynamic_cbais;
        clw.constant[1] = clw_dynamic_cbais_sh;
        clw.constant[2] = clw_dynamic_cbais_js;
    } else {
        clw.values[0].data[index] = clw.values[0].data[index] - 0 + clw_dynamic_cbais;
        clw.values[1].data[index] = clw.values[1].data[index] - 0 + clw_dynamic_cbais_sh;
        clw.values[2].data[index] = clw.values[2].data[index] - 0 + clw_dynamic_cbais_js;
        clw.constant[0] = clw_dynamic_cbais;
        clw.constant[1] = clw_dynamic_cbais_sh;
        clw.constant[2] = clw_dynamic_cbais_js;
    }
    clw_dynamic_cbais = 0;
    clw_dynamic_cbais_sh = 0;
    clw_dynamic_cbais_js = 0;
    copy(JSON.stringify(clw), path.join(__dirname, '../json/clw_copy.text'), () => {
        fs.writeFile(path.join(__dirname, '../json/clw.text'), JSON.stringify(clw), (er) => {
            if (er) {
                console.log(er);
            }
        })
    })
}
//写入错误信息
function writeErr(data) {
    const date = new Date();
    try {
        data = JSON.stringify(data)
    } catch (e) {
        data = data
    }
    fs.writeFile(path.join(__dirname, `../log/error_${date.toDateString()}.text`), data, { flag: 'a' }, function (err) {
        if (err)
            console.log(err);
    });
}
//替换文件前保存数据
function copy(data, dst, callbalck) {
    try {
        fs.writeFile(dst, data, { flag: 'w+', encoding: 'utf8' }, callbalck);
    } catch (e) {
        console.log(e)
    }
}
//开启接受数据服务
function start() {
    fs.readFile(path.join(__dirname, '..', '/json/ais_statistics_copy.text'), { encoding: 'utf8', flag: 'r' }, (err, result) => {
        if (err) {
            console.log(err);
            return
        }
        if (result) {
            try {
                ais_statistics = JSON.parse(result)
            } catch (e) {
                ais_statistics = result;
                console.error(e)
            }
        }
    });
    fs.readFile(path.join(__dirname, '..', '/json/clw_copy.text'), { encoding: 'utf8', flag: 'r' }, (err, result) => {
        if (err) {
            console.log(err);
            return
        }
        if (result) {
            try {
                global.clw = JSON.parse(result)
            } catch (e) {
                global.clw = result;
                console.error(e)
            }
        }
    });
    socket = new WebSocket('ws://120.55.85.1:8080');
    socket.on('open', function open() {
        regSend()
    });

    socket.on('message', function incoming(data) {
        try {
            data = data.replace(/\t/g, '');
            data = data.replace(/([^{])(\r\n|\n)([^}])/g, '$1\\n$3');
            JSON.parse(data);
        } catch (e) {
            writeErr({ e, data });
            return false;
        }
        let res = JSON.parse(data);
        if (res.type == "register_resp") {
            sessionId = res.info.session_id;
            heartBeat();
            subSend();
        } else {
            if (res.type == "subscribe_resp") {
                // console.log(res)
            }
            if (res.method == "NOTIFY") {
                let thisDate = new Date();
                thisDate = thisDate.getFullYear() + '-' + (thisDate.getMonth() + 1) + '-' + thisDate.getDate();
                if (csj.dates[csj.dates.length - 1] != thisDate) {
                    gskk = 0;     //高速卡口         @gskk*@
                    gsevent = 0;  //高速阻塞情况     @gaosu_event@
                    taxi = 0;     //出租车GPS        @taxi_data@
                    yys = 0;      //运营商路况信息    @lkxx_yys@
                    ali = 0;      //路况预测信息      @lkxx_ali@
                    gps_zj = 0;   //两客一危浙江      @gps@809
                    gps_sh = 0;   //两客一危上海      @gps@809.sh
                    gps_js = 0;   //两客一危江苏      @gps@809.js
                    airport = 0;  //机场大巴          @airportbus_data@
                    adsb = 0;     //航空ads数据       @adsb_data@
                    ais = 0;      //船舶ais数据       @clw_dynamic_cbais@
                    traffic = 0;   //交调实时数据      @Traffic_survey@
                    clearInterval(timer2);
                    timer2 = null;
                    clearInterval(timer);
                    timer = null;
                    handleData(csj, hituns);
                }
                if (/gps/.test(res.type) && !/ais_gps/.test(res.type)) {
                    var type = judgeArea(res.type);
                    switch (type) {
                        case 'sh':
                            csj.values[1].data[sum_key]++;
                            gps_sh++
                            sh++;
                            break;
                        case 'js':
                            csj.values[2].data[sum_key]++;
                            gps_js++
                            js++;
                            break;
                        default:
                            csj.values[0].data[sum_key]++;
                            zj++;
                            gps_zj++
                            break;
                    }
                } else if (/gskk/.test(res.type)) {
                    gskk++;
                } else {
                    switch (true) {
                        case /gaosu_event/.test(res.type):
                            gsevent++;
                            break;
                        case /taxi_data/.test(res.type):
                            taxi++;
                            break;
                        case /lkxx_yys/.test(res.type):
                            yys++;
                            break;
                        case /lkxx_ali/.test(res.type):
                            ali++;
                            break;
                        case /airportbus_data/.test(res.type):
                            airport++;
                            break;
                        case /adsb_data/.test(res.type):
                            adsb++;
                            break;
                        case /clw_dynamic_cbais/.test(res.type):
                            ais++;
                            if (/@clw_dynamic_cbais@sh/.test(res.type)) clw_dynamic_cbais_sh++
                            else clw_dynamic_cbais++
                            if (!timer_clw) {
                                timer_clw = setInterval(() => {
                                    handleClwData()
                                }, 3000)
                            }
                            break;
                        case /Traffic_survey/.test(res.type):
                            traffic++;
                            break;
                        case /ais_gps/.test(res.type):
                            let ais_gps_id = res.info.data[0];
                            ais_gps++;
                            if(/@ais_gps@js/.test(res.type)) clw_dynamic_cbais_js++
                            else if(/@ais_gps@sh/.test(res.type)) clw_dynamic_cbais_sh++
                            if (ais_statistics.ais_gps_id.indexOf(ais_gps_id) == -1) {
                                ais_gps_ex_re++;
                                ais_statistics.ais_gps_id.push(ais_gps_id)
                            }
                            if (!timer_ais) {
                                timer_ais = setInterval(() => {
                                    handleAisData()
                                }, 500)
                            }
                            break;
                        case /ais_static/.test(res.type):
                            let ais_static_id = res.info.data[0];
                            ais_static++;
                            if (ais_statistics.ais_static_id.indexOf(ais_static_id) == -1) {
                                ais_static_ex_re++;
                                ais_statistics.ais_static_id.push(ais_static_id)
                            }
                            if (!timer_ais) {
                                timer_ais = setInterval(() => {
                                    handleAisData()
                                }, 500)
                            }
                            break;
                        default:
                            console.log(res.type);
                            break;
                    }
                }
            }
        }
    });
    function judgeArea(value) {
        var area = value.split('.')
        if (area.length == 1) return 'zj';
        else {
            if (area[1] == 'sh') return 'sh'
            if (area[1] == 'js') return 'js'
        }
    }
    function send(msg) {
        if (!socket || socket.readyState != 1) { } else {
            if (socket.bufferedAmount == 0) {
                socket.send(JSON.stringify(msg));
            } else {
                console.log('socket.bufferedAmount != 0');
            }
        }
    }

    function guid() {
        function S4() {
            return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
        }
        return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
    }

    //关闭WebSocket连接

    function closeWebSocket() {
        if (socket.readyState == 1)
            socket.close();
    }


    function heartBeat() {
        var message2 = {
            'method': 'INFO',
            'from': sessionId,
            'type': 'heart_beat',
            'call_id': Guid
        }
        the_heart = setInterval(function () {
            if (socket.readyState == 1) {
                send(message2);
            } else {
                clearInterval(the_heart);
                console.log('您已断开连接');
            }
        }, 20000);
    }
    //注册

    function regSend() {
        certificate = {
            "info": {
                "ver": 2,
                "sn": "{51A90785-962A-420A-8C1F-3418ACF51176}",
                "user": "杭州皓天信息技术有限公司",
                "begin": "2018-12-28",
                "end": "2019-12-31",
                "area": "test",
                "ip": "",
                "idlist": "",
                "subscribe": "@*@",
                "notify": "@*@",
                "send": "*",
                "limit": 20,
                "localhost": false,
                "email": "langjm@hituns.com",
                "tel": "15757173290",
                "server_id": ""
            },
            "check": "d61b17a650b80340c773b0323f6e4d29"
        };
        var message = {
            'method': 'REGISTER',
            'type': 'register_req',
            'call_id': Guid,
            'info': {
                'certificate': JSON.stringify(certificate)
            }
        };
        send(message);
    }

    //订阅
    function subSend() {
        var message = {
            'method': 'REGISTER',
            'type': 'subscribe_req',
            'from': sessionId,
            'call_id': Guid,
            'info': {
                'subscribe':
                //csj数据
                '[85][0-9]{1,}@gps@809;@gps@809.sh;@gps@809.js;' +
                //hituns所有数据
                '@gskk*@;@gaosu_event@;@taxi_data@;@lkxx_yys@;@lkxx_ali@;@gps@809;@gps@809.sh;@gps@809.js;@airportbus_data@;@adsb_data@;@clw_dynamic_cbais@;@Traffic_survey@;' +
                //ais数据
                '@ais_gps@;@ais_static@;' +
                //clw数据
                '@clw_dynamic_cbais@'
            }
        };
        send(message);
    }

}
module.exports = read;